1 /*
2 * Scope: a generic MVC framework.
3 * Copyright (c) 2000-2002, The Scope team
4 * All rights reserved.
5 *
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * Neither the name "Scope" nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 *
36 * $Id: STable.java,v 1.22 2002/09/13 17:04:41 ludovicc Exp $
37 */
38 package org.scopemvc.view.swing;
39
40
41 import java.awt.Component;
42 import java.awt.event.MouseEvent;
43 import java.awt.event.MouseListener;
44 import java.math.BigDecimal;
45 import java.math.BigInteger;
46 import java.util.HashMap;
47 import javax.swing.DefaultCellEditor;
48 import javax.swing.JCheckBox;
49 import javax.swing.JLabel;
50 import javax.swing.JTable;
51 import javax.swing.JToolTip;
52 import javax.swing.ListSelectionModel;
53 import javax.swing.table.TableCellEditor;
54 import javax.swing.table.TableCellRenderer;
55 import javax.swing.table.TableModel;
56 import org.apache.commons.logging.Log;
57 import org.apache.commons.logging.LogFactory;
58 import org.scopemvc.core.Control;
59 import org.scopemvc.core.Controller;
60 import org.scopemvc.core.Selector;
61 import org.scopemvc.core.View;
62
63 /***
64 * <P>
65 *
66 * A JTable bound to a list property of a model. The table shows a list of rows
67 * from the bound property (see {@link #setSelector}). If the rows are model
68 * objects, the properties shown for each column are set using {@link
69 * #setColumnSelectors}. See also {@link #setColumnNames}. </P> <P>
70 *
71 * STable uses {@link STableModel} and so the contents can be sorted using
72 * {@link SAbstractListModel#setSorted(boolean) setSorted(boolean)} or {@link
73 * SAbstractListModel#setSorted(java.util.Comparator) setSorted(Comparator)}.
74 * </P> <P>
75 *
76 * STable uses a standard (non-bound) Swing ListSelectionModel unless a
77 * selection Selector is set using {@link #setSelectionSelector} or {@link
78 * #setSelectionSelectorString} in which case a bound SListSelectionModel is
79 * used. This allows both single-selection and an as-yet-limited multiselection
80 * (contiguous only) using a HashSet property to hold the selected objects. See
81 * {@link SListSelectionModel}, which is used by STable to maintain bound
82 * selections. </P>
83 *
84 * @author <A HREF="mailto:daniel.michalik@autel.cz">Daniel Michalik</A>
85 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A>
86 * @created 05 September 2002
87 * @version $Revision: 1.22 $ $Date: 2002/09/13 17:04:41 $
88 */
89 public class STable extends JTable
90 implements View, Refreshable, MouseListener, ListSelectionParent {
91
92 private static final Log LOG = LogFactory.getLog(STable.class);
93
94 // --------------------- Default renderer and editors ---------------------
95
96 /***
97 * TODO: describe of the Field
98 */
99 protected HashMap editors;
100
101 // ------------- Support validation failures from selection -------------
102
103 /***
104 * Helper to manage validation state.
105 */
106 private ValidationHelper validationHelper = new ValidationHelper(this);
107
108 // -------------------- Controls -----------------------
109
110 /***
111 * Control to issue on selection change.
112 */
113 private String selectionControlID;
114
115 /***
116 * Control to issue on double click.
117 */
118 private String doubleClickControlID;
119
120
121 /***
122 * Constructor for the STable object
123 */
124 public STable() {
125 super(null, null, null);
126 // single selection only for now
127 // setAutoCreateColumnsFromModel(false);
128 addMouseListener(this);
129 }
130
131
132 // protected ListSelectionModel createDefaultSelectionModel() {
133 // return new SListSelectionModel(this);
134 // }
135
136
137 // ------------------ Implement View by delegation to STableModel and selection
138
139
140 /***
141 * Gets the bound model
142 *
143 * @return The boundModel value
144 */
145 public final Object getBoundModel() {
146 return ((STableModel) getModel()).getBoundModel();
147 }
148
149
150 // --------- Set up table binding by delegation -------------
151
152 /***
153 * Gets the selector
154 *
155 * @return The selector value
156 */
157 public final Selector getSelector() {
158 return ((STableModel) getModel()).getSelector();
159 }
160
161
162 /***
163 * Gets the selection selector
164 *
165 * @return The selectionSelector value
166 */
167 public final Selector getSelectionSelector() {
168 return ((SListSelectionModel) getSelectionModel()).getSelector();
169 }
170
171
172 /***
173 * TODO: document the method
174 */
175 public void issueChangeSelectionControl() {
176 if (selectionControlID != null) {
177 Control control = new Control(selectionControlID);
178 issueControl(control);
179 }
180 }
181
182
183 /***
184 * Get the Control ID for the Control that will be issued when the selection
185 * is changed.
186 *
187 * @return The changeSelectionControlID value
188 */
189 public String getChangeSelectionControlID() {
190 return selectionControlID;
191 }
192
193
194 /***
195 * Get the Control ID for the Control that will be issued when the List is
196 * double-clicked.
197 *
198 * @return The doubleClickControlID value
199 */
200 public String getDoubleClickControlID() {
201 return doubleClickControlID;
202 }
203
204
205 /***
206 * Don't assign a direct Controller to List, instead delegate to the
207 * containing SwingView that has a parent Controller.
208 *
209 * @return The controller value
210 */
211 public Controller getController() {
212 return null;
213 }
214
215
216 /***
217 * Don't assign a direct Controller to List, instead delegate to the
218 * containing SwingView that has a parent Controller.
219 *
220 * @param inControl TODO: Describe the Parameter
221 */
222 public void issueControl(Control inControl) {
223 SwingUtil.issueControl(this, inControl);
224 }
225
226
227 // public TableCellEditor getCellEditor(int row, int column) {
228 // Class clazz = getModel().getColumnClass(column);
229 // TableCellEditor result = (TableCellEditor)editors.get(clazz);
230 // if (LOG.isDebugEnabled()) LOG.debug("getCellEditor: " + result);
231 // if (result == null) {
232 // result = new STableTextCellEditor(clazz);
233 // }
234 // return result;
235 // }
236
237
238 /***
239 * Gets the default editor
240 *
241 * @param columnClass TODO: Describe the Parameter
242 * @return The defaultEditor value
243 */
244 public TableCellEditor getDefaultEditor(Class columnClass) {
245 if (columnClass == null) {
246 return null;
247 } else {
248 Object editor = editors.get(columnClass);
249 if (editor != null) {
250 return (TableCellEditor) editor;
251 } else {
252 return new STableTextCellEditor(columnClass);
253 // getDefaultEditor(columnClass.getSuperclass());
254 }
255 }
256 }
257
258
259 /***
260 * Gets the default renderer
261 *
262 * @param columnClass TODO: Describe the Parameter
263 * @return The defaultRenderer value
264 */
265 public TableCellRenderer getDefaultRenderer(Class columnClass) {
266 if (columnClass == null) {
267 return null;
268 } else {
269 Object renderer = super.getDefaultRenderer(columnClass);
270 if (renderer != null) {
271 return (TableCellRenderer) renderer;
272 } else {
273 return new SDefaultTableCellRenderer(columnClass);
274 // getDefaultRenderer(columnClass.getSuperclass());
275 }
276 }
277 }
278
279
280 /***
281 * Sets the bound model
282 *
283 * @param inModel The new boundModel value
284 */
285 public final void setBoundModel(Object inModel) {
286 ((STableModel) getModel()).setBoundModel(inModel);
287 if (getSelectionModel() instanceof SListSelectionModel) {
288 ((SListSelectionModel) getSelectionModel()).setBoundModel(inModel);
289 }
290 }
291
292 /***
293 * Set the Selector for the table data. Should be a java.util.List or an
294 * Object[] or have a "size" property and properties accessible by an
295 * IntIndexedSelector.
296 *
297 * @param inSelector The new selector value
298 */
299 public final void setSelector(Selector inSelector) {
300 ((STableModel) getModel()).setSelector(inSelector);
301 }
302
303
304 /***
305 * Set the Selector for the table data. Should be a java.util.List or an
306 * Object[] or have a "size" property and properties accessible by an
307 * IntIndexedSelector.
308 *
309 * @param inSelectorString The new selectorString value
310 */
311 public final void setSelectorString(String inSelectorString) {
312 ((STableModel) getModel()).setSelectorString(inSelectorString);
313 }
314
315 /***
316 * Set the Selector for the list selection: this property will be bound to
317 * the list's single selection.
318 *
319 * @param inSelector The new selectionSelector value
320 */
321 public final void setSelectionSelector(Selector inSelector) {
322 if (inSelector != null) {
323 setSelectionModel(new SListSelectionModel(this));
324 ((SListSelectionModel) getSelectionModel()).setSelector(inSelector);
325 } else {
326 setSelectionModel(createDefaultSelectionModel());
327 }
328 }
329
330
331 /***
332 * Set the Selector for the list selection: this property will be bound to
333 * the list's single selection.
334 *
335 * @param inSelectorString The new selectionSelectorString value
336 */
337 public final void setSelectionSelectorString(String inSelectorString) {
338 if (inSelectorString != null) {
339 setSelectionModel(new SListSelectionModel(this));
340 ((SListSelectionModel) getSelectionModel()).setSelectorString(inSelectorString);
341 } else {
342 setSelectionModel(createDefaultSelectionModel());
343 }
344 }
345
346
347 /***
348 * Set the Control ID for the Control that will be issued when the selection
349 * is changed. If null no Control will be issued.
350 *
351 * @param inControlID The new changeSelectionControlID value
352 */
353 public final void setChangeSelectionControlID(String inControlID) {
354 selectionControlID = inControlID;
355 }
356
357 /***
358 * Set the Control ID for the Control that will be issued when the List is
359 * double-clicked. If null no Control will be issued.
360 *
361 * @param inControlID The new doubleClickControlID value
362 */
363 public final void setDoubleClickControlID(String inControlID) {
364 doubleClickControlID = inControlID;
365 }
366
367
368 /***
369 * Set up the column selectors.
370 *
371 * @param inSelectors The new columnSelectors value
372 */
373 public void setColumnSelectors(Selector[] inSelectors) {
374 ((STableModel) getModel()).setColumnSelectors(inSelectors);
375 createDefaultColumnsFromModel();
376 }
377
378
379 /***
380 * Set up the column selectors.
381 *
382 * @param inSelectorStrings The new columnSelectorStrings value
383 */
384 public void setColumnSelectorStrings(String[] inSelectorStrings) {
385 ((STableModel) getModel()).setColumnSelectorStrings(inSelectorStrings);
386 createDefaultColumnsFromModel();
387 }
388
389
390 /***
391 * Set up the column names.
392 *
393 * @param inNames The new columnNames value
394 */
395 public void setColumnNames(String[] inNames) {
396 ((STableModel) getModel()).setColumnNames(inNames);
397 createDefaultColumnsFromModel();
398 }
399
400 /***
401 * Don't assign a Controller to this component, instead delegate to the
402 * containing SwingView that has a parent Controller.
403 *
404 * @param inController The new controller value
405 */
406 public void setController(Controller inController) {
407 throw new UnsupportedOperationException("Can't assign a Controller to a " + getClass());
408 }
409
410 // ------------------ Refreshable -------------------------
411
412 /***
413 * TODO: document the method
414 */
415 public void refresh() {
416 ((STableModel) getModel()).refresh();
417 refreshSelection();
418 }
419
420
421 // ------------- Support maintaining selection when list data changes ----------
422
423 /***
424 * TODO: document the method
425 */
426 public void refreshSelection() {
427 ListSelectionModel s = getSelectionModel();
428 if (s instanceof SListSelectionModel) {
429 ((SListSelectionModel) s).refresh();
430 }
431 }
432
433
434 // ------------- Implement SingleListSelectionParent ----------------
435
436 /***
437 * @param inValue TODO: Describe the Parameter
438 * @return -1 if not found.
439 */
440 public int findIndexFor(Object inValue) {
441 if (inValue == null) {
442 return -1;
443 }
444 for (int i = getModel().getRowCount() - 1; i >= 0; --i) {
445 if (inValue.equals(((SAbstractListModel) getModel()).getElementAt(i))) {
446 return i;
447 }
448 }
449 return -1;
450 }
451
452
453 /***
454 * @param inIndex TODO: Describe the Parameter
455 * @return null if not found.
456 */
457 public Object findElementAt(int inIndex) {
458 if (inIndex < 0) {
459 return null;
460 }
461 try {
462 return ((SAbstractListModel) getModel()).getElementAt(inIndex);
463 } catch (Exception e) {
464 LOG.warn("Can't findElementAt: " + inIndex, e);
465 }
466 return null;
467 }
468
469
470 /***
471 * TODO: document the method
472 *
473 * @param inException TODO: Describe the Parameter
474 */
475 public void validationFailed(Exception inException) {
476 validationHelper.validationFailed(inException);
477 }
478
479
480 /***
481 * TODO: document the method
482 */
483 public void validationSuccess() {
484 validationHelper.validationSuccess();
485 }
486
487
488 /***
489 * TODO: document the method
490 *
491 * @return TODO: Describe the Return Value
492 */
493 public JToolTip createToolTip() {
494 return validationHelper.createToolTip(super.createToolTip());
495 }
496
497
498 /***
499 * TODO: document the method
500 *
501 * @param e TODO: Describe the Parameter
502 */
503 public void mouseClicked(MouseEvent e) {
504 if (e.getClickCount() == 2) {
505 if (doubleClickControlID != null) {
506 Control control = new Control(doubleClickControlID);
507 issueControl(control);
508 }
509 }
510 }
511
512
513 /***
514 * TODO: document the method
515 *
516 * @param e TODO: Describe the Parameter
517 */
518 public void mousePressed(MouseEvent e) { }
519
520 /***
521 * TODO: document the method
522 *
523 * @param e TODO: Describe the Parameter
524 */
525 public void mouseReleased(MouseEvent e) { }
526
527 /***
528 * TODO: document the method
529 *
530 * @param e TODO: Describe the Parameter
531 */
532 public void mouseEntered(MouseEvent e) { }
533
534 /***
535 * TODO: document the method
536 *
537 * @param e TODO: Describe the Parameter
538 */
539 public void mouseExited(MouseEvent e) { }
540
541
542 /***
543 * STables create their own STableModel by default.
544 *
545 * @return TODO: Describe the Return Value
546 */
547 protected TableModel createDefaultDataModel() {
548 return new STableModel(this);
549 }
550
551
552 /***
553 * Sets default Scope table cell renderers. They use Scope's
554 * StringConverters.
555 */
556 protected void createDefaultRenderers() {
557 if (LOG.isDebugEnabled()) {
558 LOG.debug("create DefaultRenderers for STable");
559 }
560
561 super.createDefaultRenderers();
562 // else updateUI() fails in superclass
563
564 setDefaultRenderer(Boolean.class, new BooleanRenderer());
565 setDefaultRenderer(Boolean.TYPE, new BooleanRenderer());
566
567 SDefaultTableCellRenderer rend = new SDefaultTableCellRenderer(Double.class);
568 rend.setHorizontalAlignment(JLabel.RIGHT);
569 setDefaultRenderer(Double.class, rend);
570 setDefaultRenderer(Double.TYPE, rend);
571
572 rend = new SDefaultTableCellRenderer(Float.class);
573 rend.setHorizontalAlignment(JLabel.RIGHT);
574 setDefaultRenderer(Float.class, rend);
575 setDefaultRenderer(Float.TYPE, rend);
576
577 rend = new SDefaultTableCellRenderer(Integer.class);
578 rend.setHorizontalAlignment(JLabel.RIGHT);
579 setDefaultRenderer(Integer.class, rend);
580 setDefaultRenderer(Integer.TYPE, rend);
581
582 rend = new SDefaultTableCellRenderer(Long.class);
583 rend.setHorizontalAlignment(JLabel.RIGHT);
584 setDefaultRenderer(Long.class, rend);
585 setDefaultRenderer(Long.TYPE, rend);
586
587 rend = new SDefaultTableCellRenderer(BigInteger.class);
588 rend.setHorizontalAlignment(JLabel.RIGHT);
589 setDefaultRenderer(BigInteger.class, rend);
590
591 rend = new SDefaultTableCellRenderer(BigDecimal.class);
592 rend.setHorizontalAlignment(JLabel.RIGHT);
593 setDefaultRenderer(BigDecimal.class, rend);
594 }
595
596
597 /***
598 * TODO: document the method
599 */
600 protected void createDefaultEditors() {
601
602 super.createDefaultEditors();
603 // else updateUI() fails in superclass
604
605 editors = new HashMap();
606
607 editors.put(Boolean.class, new BooleanEditor());
608 editors.put(Boolean.TYPE, new BooleanEditor());
609 }
610
611
612 static class BooleanRenderer extends JCheckBox implements TableCellRenderer {
613 /***
614 * Constructor for the BooleanRenderer object
615 */
616 public BooleanRenderer() {
617 super();
618 setHorizontalAlignment(JLabel.CENTER);
619 }
620
621 /***
622 * Gets the table cell renderer component
623 *
624 * @param table TODO: Describe the Parameter
625 * @param value TODO: Describe the Parameter
626 * @param isSelected TODO: Describe the Parameter
627 * @param hasFocus TODO: Describe the Parameter
628 * @param row TODO: Describe the Parameter
629 * @param column TODO: Describe the Parameter
630 * @return The tableCellRendererComponent value
631 */
632 public Component getTableCellRendererComponent(JTable table, Object value,
633 boolean isSelected, boolean hasFocus, int row, int column) {
634 if (isSelected) {
635 setForeground(table.getSelectionForeground());
636 super.setBackground(table.getSelectionBackground());
637 } else {
638 setForeground(table.getForeground());
639 setBackground(table.getBackground());
640 }
641 setSelected((value != null && ((Boolean) value).booleanValue()));
642 return this;
643 }
644 }
645
646
647 static class BooleanEditor extends DefaultCellEditor {
648 /***
649 * Constructor for the BooleanEditor object
650 */
651 public BooleanEditor() {
652 super(new JCheckBox());
653 JCheckBox checkBox = (JCheckBox) getComponent();
654 checkBox.setHorizontalAlignment(JCheckBox.CENTER);
655 }
656 }
657 }
This page was automatically generated by Maven